home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / pcr / pcr4_4.lha / DIST / debugnub / CirioNubRuntime.c < prev    next >
C/C++ Source or Header  |  1992-03-04  |  18KB  |  773 lines

  1. /* begincopyright
  2.   Copyright (c) 1988 Xerox Corporation. All rights reserved.
  3.   Use and copying of this software and preparation of derivative works based
  4.   upon this software are permitted. Any distribution of this software or
  5.   derivative works must comply with all applicable United States export
  6.   control laws. This software is made available AS IS, and Xerox Corporation
  7.   makes no warranty about the software, its performance or its conformity to
  8.   any specification. Any person obtaining a copy of this software is requested
  9.   to send their name and post office or electronic mail address to:
  10.     PCR Coordinator
  11.     Xerox PARC
  12.     3333 Coyote Hill Rd.
  13.     Palo Alto, CA 94304
  14.   endcopyright */
  15.  
  16. /*
  17.  * CirioNubRuntime.c
  18.  *
  19.  * Demers, February 20, 1990 3:56:47 pm PST
  20.  * Agostino, June 12, 1991 9:40:02 am PDT
  21.  */
  22.  
  23. #include "xr/Errno.h"
  24. #include "xr/ThreadsBackdoor.h"
  25. #include "xr/ThreadsSlaveIOP.h"
  26. #include "xr/ThreadsSignalsPrivate.h"
  27. #include "xr/CirioNubProtocol.h"
  28. #include "xr/CirioNubPrivate.h"
  29. #include "xr/CirioNubInstall.h"
  30. #include "xr/CirioNubMarshall.h"
  31.  
  32. #include "xr/ThreadsMsg.h"
  33.  
  34. #include <sys/socket.h>
  35. #include <netinet/tcp.h>
  36.  
  37. extern int errno;
  38.  
  39. /*
  40.  * Global state on slave processor
  41.  */
  42.  
  43. static CirioNubData cnd;
  44.  
  45.  
  46. /*
  47.  * Debugging messages
  48.  */
  49.  
  50. void CirioDBM(fmt, x1, x2, x3, x4, x5)
  51.     char *fmt;
  52.     int x1, x2, x3, x4, x5;
  53. {
  54.     static int gotEnv = FALSE;
  55.     static int pcm;
  56.     
  57.     if( !gotEnv ) {
  58.         extern char *(getenv());
  59.         char *env = getenv("CirioPrintConsoleMessages");
  60.         pcm = (env != NIL);
  61.         gotEnv = TRUE;
  62.     }
  63.     if( pcm ) XR_ConsoleMsg(fmt, x1, x2, x3, x4, x5);
  64. }
  65.  
  66.  
  67. /*
  68.  * Marshalling stuff
  69.  */
  70.  
  71.  
  72. /*
  73.     wait for descriptor ready (or just wait if descriptor < 0).
  74.     Return 0 on timeout, 1 if ready, (-errno) on error.
  75.     Note the error may be EINTR.
  76. */
  77.  
  78. static int
  79. CirioNubWaitDescriptorReady(fd, in, mSecs)
  80.     int fd;
  81.     bool in;
  82.     unsigned mSecs;
  83. {
  84.     struct timeval timeout;
  85.     int fdBuf;
  86.     int *ip = NIL;
  87.     int *op = NIL;
  88.     int *xp = NIL;
  89.     int ans;
  90.  
  91.     timeout.tv_sec = mSecs/1000;
  92.     timeout.tv_usec = (mSecs % 1000) * 1000;
  93.     if( fd >= 0 ) {
  94.         fdBuf = 01 << fd;
  95.         if( in ) ip = &fdBuf; else op = &fdBuf;
  96.     }
  97.     ans = select(32, ip, op, xp, &timeout);
  98.     return ((ans >= 0) ? ans : (-errno));
  99. }
  100.  
  101.  
  102. /*
  103.     accept
  104. */
  105.  
  106. static int
  107. CirioNubAccept(fd, ap, lenp)
  108.     int fd;
  109.     struct sockaddr_in *ap;
  110.     int *lenp;
  111. {
  112.     int ans;
  113.     int savedLen = *lenp;
  114.     XR_SignalState oldState;
  115.  
  116.     oldState = XR_EnableSignals();
  117.     for(;;) {
  118.         ans = CirioNubWaitDescriptorReady(fd, TRUE, 5000);
  119.         if( ans <= 0 ) {
  120.             if( (ans < 0) && (ans != (-EINTR)) ) break;
  121.         } else {
  122.             *lenp = savedLen;
  123.             ans = accept(fd, ap, lenp);
  124.             if( ans < 0 ) ans = (-errno);
  125.             if( ans != (-EINTR) ) break;
  126.         }
  127.     }
  128.     XR_SetSignalState(oldState);
  129.     return ans;
  130. }
  131.  
  132.  
  133. /*
  134.     read/write without returning short result
  135. */
  136.  
  137.  
  138. static CirioNubRetCode
  139. CirioNubDoIOUntilDone(fd, in, buf, nBytes)
  140.     int fd;
  141.     bool in;
  142.     char *buf;
  143.     int nBytes;
  144. {
  145.     int ans;
  146.     CirioNubRetCode retCode = cnrc_comm;
  147.     XR_SignalState oldState;
  148.  
  149.     oldState = XR_EnableSignals();
  150.     for(;;) {
  151.         ans = CirioNubWaitDescriptorReady(fd, in, 5000);
  152.         if( (ans == 0) || (ans == (-EINTR)) ) continue;
  153.         ans = (in ? read(fd, buf, nBytes) : write(fd, buf, nBytes));
  154.         if( ans < 0 ) ans = (-errno);
  155.         if( ans == (-EINTR) ) continue;
  156.         if( ans < 0 ) break;
  157.         if( (ans == 0) && in ) break;
  158.         nBytes -= ans;
  159.         buf += ans;
  160.         if( nBytes <= 0 ) { retCode = cnrc_ok; break; }
  161.     }
  162.   Out:
  163.     XR_SetSignalState(oldState);
  164.     return retCode;
  165. }
  166.  
  167.  
  168. #define readall(fd, buf, nBytes) \
  169.     CirioNubDoIOUntilDone((fd), TRUE, (buf), (nBytes))
  170.  
  171. #define writeall(fd, buf, nBytes) \
  172.     CirioNubDoIOUntilDone((fd), FALSE, (buf), (nBytes))
  173.  
  174.  
  175.  
  176. /*
  177.  * Send data with type info
  178.  */
  179.  
  180.  
  181.  
  182. static CirioNubRetCode
  183. CirioNubPut32Inner(n, tag)
  184.     unsigned n;
  185.     enum CirioNubTag tag;
  186. {
  187.     struct {
  188.     struct CirioNubWrapper w;
  189.     net_long x;
  190.     } buf;
  191.  
  192.     buf.w.cnw_tag = htons(((short)(tag)));
  193.     buf.w.cnw_len = htons( (sizeof n) );
  194.     buf.x = htonl(n);
  195.     return writeall(cnd->cnd_rpcFD, &buf, (sizeof buf));
  196. }
  197.  
  198.  
  199. #define CirioNubPutRetCode(c)    CirioNubPut32Inner(((unsigned)(c)),cnt_retCode)
  200.  
  201. #define CirioNubPutProcID(id)    CirioNubPut32Inner(((unsigned)(id)),cnt_procID)
  202.  
  203. CirioNubRetCode
  204. CirioNubPutCard32(n)
  205.     unsigned n;
  206. {
  207.     return CirioNubPut32Inner(((unsigned)(n)), cnt_card32);
  208. }
  209.  
  210.  
  211. CirioNubRetCode
  212. CirioNubPutInt32(n)
  213.     int n;
  214. {
  215.     return CirioNubPut32Inner(((unsigned)(n)), cnt_int32);
  216. }
  217.  
  218.  
  219. static CirioNubRetCode
  220. CirioNubPutBlock8Inner(b, len, tag)
  221.     char *b;
  222.     int len;
  223.     enum CirioNubTag tag;
  224. {
  225.     struct CirioNubWrapper w;
  226.     CirioNubRetCode ans;
  227.  
  228.     w.cnw_tag = htons(((short)(tag)));
  229.     w.cnw_len = htons(len);
  230.     if( (ans = writeall(cnd->cnd_rpcFD, &w, (sizeof w))) != cnrc_ok ) {
  231.     return(ans);
  232.     }
  233.     if( len == 0 ) return(cnrc_ok);
  234.     if( (ans = writeall(cnd->cnd_rpcFD, b, len)) != cnrc_ok ) {
  235.     return(ans);
  236.     }
  237.     if( len & 03 ) {
  238.      int slop = 4 - (len & 03);
  239.      int zero = 0;
  240.      if( (ans = writeall(cnd->cnd_rpcFD, &zero, slop)) != cnrc_ok ) {
  241.         return(ans);
  242.     }
  243.     }
  244.     return(cnrc_ok);
  245. }
  246.  
  247.  
  248. CirioNubRetCode
  249. CirioNubPutString(s)
  250.     char *s;
  251. {
  252.     return( CirioNubPutBlock8Inner(s, strlen(s), cnt_string) );
  253. }
  254.  
  255.  
  256. CirioNubRetCode
  257. CirioNubPutBlock8(b, len)
  258.     char *b;
  259.     int len;
  260. {
  261.     return( CirioNubPutBlock8Inner(b, len, cnt_block8) );
  262. }
  263.  
  264.  
  265. CirioNubRetCode
  266. CirioNubPutBlock16(b, len)
  267.     short *b;
  268.     int len;
  269. {
  270.     struct CirioNubWrapper w;
  271.     CirioNubRetCode ans;
  272.     int zero = 0;
  273.  
  274.     b = (short *)(((unsigned)(b)) & (~01));
  275.     len = (len + 1) & (~01);
  276.     w.cnw_tag = htons(cnt_block16);
  277.     w.cnw_len = htons(len);
  278.     /* removed extra call to writeall -- mna 6/12/91 */
  279.     if( (ans = writeall(cnd->cnd_rpcFD, &w, (sizeof w))) != cnrc_ok ) {
  280.     return(ans);
  281.     }
  282.     if( len == 0 ) return(cnrc_ok);
  283.     if( htons(1) != 1 ) {
  284.     int cnt = len;
  285.     short *p = b;
  286.     while( cnt > 0 ) { *p = htons(*p); p++; cnt-= 2; }
  287.     }
  288.     if( (ans = writeall(cnd->cnd_rpcFD, b, len)) == cnrc_ok ) {
  289.     if( (len & 03) != 0 ) {
  290.         ans = writeall(cnd->cnd_rpcFD, &zero, 2);
  291.     }
  292.     }
  293.     if( htons(1) != 1 ) {
  294.     int cnt = len;
  295.     short *p = b;
  296.     while( cnt > 0 ) { *p = ntohs(*p); p++; cnt-= 2; }
  297.     }
  298.     return( ans );
  299. }
  300.  
  301.  
  302. CirioNubRetCode
  303. CirioNubPutBlock32(b, len)
  304.     long *b;
  305.     int len;
  306. {
  307.     struct CirioNubWrapper w;
  308.     CirioNubRetCode ans;
  309.  
  310.     b = (long *)(((unsigned)(b)) & (~03));
  311.     len = (len + 3) & (~03);
  312.     w.cnw_tag = htons(cnt_block32);
  313.     w.cnw_len = htons(len);
  314.     if( (ans = writeall(cnd->cnd_rpcFD, &w, (sizeof w))) != cnrc_ok ) {
  315.     return(ans);
  316.     }
  317.     if( len == 0 ) return(cnrc_ok);
  318.     if( htons(1) != 1 ) {
  319.     int cnt = len;
  320.     long *p = b;
  321.     while( cnt > 0 ) { *p = htonl(*p); p++; cnt-= 4; }
  322.     }
  323.     ans = writeall(cnd->cnd_rpcFD, b, len);
  324.     if( htons(1) != 1 ) {
  325.     int cnt = len;
  326.     long *p = b;
  327.     while( cnt > 0 ) { *p = ntohl(*p); p++; cnt-= 4; }
  328.     }
  329.     return( ans );
  330. }
  331.  
  332.  
  333. CirioNubRetCode
  334. CirioNubGetCard32(b)
  335.     unsigned *b;
  336. {
  337.     CirioNubRetCode ans;
  338.     unsigned buf;
  339.  
  340.     if( (ans = readall(cnd->cnd_rpcFD, &buf, (sizeof buf))) != cnrc_ok )
  341.     return(ans);
  342.     *b = ntohl(buf);
  343.     return(cnrc_ok);
  344. }
  345.  
  346.  
  347. #define CirioNubGetInt32(b)    CirioNubGetCard32( ((unsigned *)(b)) )
  348.  
  349. /* all lengths below are rounded up to full 32-bit words */
  350.  
  351. CirioNubRetCode
  352. CirioNubGetBlock8(b, len)
  353.     char *b;
  354.     int len;
  355. {
  356.     len = (len + 3) & (~03);
  357.     return( readall(cnd->cnd_rpcFD, b, len) );
  358. }
  359.  
  360.  
  361. CirioNubRetCode
  362. CirioNubGetBlock16(b, len)
  363.     short *b;
  364.     int len;
  365. {
  366.     CirioNubRetCode ans;
  367.  
  368.     if( len == 0 ) return(cnrc_ok);
  369.     b = (short *)(((unsigned)(b)) & (~01));
  370.     len = (len + 3) & (~03);
  371.     if( (ans = readall(cnd->cnd_rpcFD, b, len)) != cnrc_ok ) return(ans);
  372.     if( htons(1) != 1 ) {
  373.     while( len > 0 ) { *b = ntohs(*b); b++; len -= 2; }
  374.     }
  375.     return(cnrc_ok);
  376. }
  377.  
  378.  
  379. CirioNubRetCode
  380. CirioNubGetBlock32(b, len)
  381.     long *b;
  382.     int len;
  383. {
  384.     CirioNubRetCode ans;
  385.  
  386.     if( len == 0 ) return(cnrc_ok);
  387.     b = (long *)(((unsigned)(b)) & (~03));
  388.     len = (len + 3) & (~03);
  389.     if( (ans = readall(cnd->cnd_rpcFD, b, len)) != cnrc_ok ) return(ans);
  390.     if( htonl(1) != 1 ) {
  391.     while( len > 0 ) { *b = ntohl(*b); b++; len -= 4; }
  392.     }
  393.     return(cnrc_ok);
  394. }
  395.  
  396.  
  397. #define HASH(d,id)    ((id) & ((d)->cnd_numHdrs-1))
  398.  
  399. static CirioNubRetCode
  400. CirioNubDispatch(procID, argc, argp)
  401.     int procID;
  402.     int argc;
  403.     unsigned *argp;
  404. {
  405.     struct CirioNubProcEntry *cnpe;
  406.     enum CirioNubRetCode retCode, ans;
  407.  
  408.     retCode = cnrc_noProc;
  409.     for( cnpe = cnd->cnd_procEntries[HASH(cnd,procID)]
  410.         ; cnpe != NIL
  411.         ; cnpe = cnpe->cnpe_next
  412.     ) {
  413.         if( cnpe->cnpe_procID == procID ) {
  414.             retCode = (
  415.         (cnpe->cnpe_clientData == NIL)
  416.             ? (*(cnpe->cnpe_proc))(argc, argp)
  417.             : (*(cnpe->cnpe_proc))(argc, argp, cnpe->cnpe_clientData)
  418.         );
  419.             break;
  420.         }
  421.     }
  422.     if( retCode < cnrc_MUST_CLOSE_CONNECTION ) {
  423.     if( (ans = CirioNubPutRetCode(retCode)) != cnrc_ok ) retCode = ans;
  424.     }
  425.     return( retCode );
  426. }
  427.  
  428.  
  429. static CirioNubRetCode
  430. CirioNubProcessCall()
  431. {
  432.     CirioNubRetCode ans;
  433.     struct CirioNubWrapper w;
  434.     unsigned procID;
  435.     int len, roundedLen, roundedLenWithNull;
  436.     char *p;
  437.     unsigned *argp;
  438.     unsigned *buffer = ((unsigned *)(cnd->cnd_callBuf));
  439.  
  440. #   define NEEDSPACE(n) \
  441.     if ( (((char *)(argp)) + (n)) > p ) { ans = cnrc_space; goto Out; }
  442.  
  443.  
  444.     argp = buffer;
  445.     p = ((char *)(buffer)) + (cnd->cnd_callBufBytes);
  446.     CirioDBM("Cirio-> ");
  447.     for(;;) {
  448.     if( (ans = readall(cnd->cnd_rpcFD, &w, (sizeof w))) != cnrc_ok ) {
  449.             CirioDBM("Cirio bad read %d\n", ans);
  450.         goto Out;
  451.     }
  452.         CirioDBM(". ");
  453.     len = (int)(ntohs(w.cnw_len));
  454.     roundedLen = (len + 03) & (~03);
  455.     switch( ntohs(w.cnw_tag) ) {
  456.         case cnt_procID:
  457.                 if( (ans = CirioNubGetCard32(&procID)) == cnrc_ok ) {
  458. #                   ifdef GCNOTINTHREAD
  459.                 if( XR_sysArea->sa_heapNum != XR_iope->iope_heapNum ) {
  460.                     /* update heap memory map */
  461.                     /* (order of following two lines is important!) */
  462.                     XR_iope->iope_heapNum = XR_sysArea->sa_heapNum;
  463.                     XR_MapSeg2( &(XR_iope->iope_seg),
  464.                             &(XR_sysArea->sa_heapSeg) );
  465.             }
  466. #                   endif
  467.             CirioDBM("proc %d ", procID);
  468.                     ans = CirioNubDispatch(procID, (argp-buffer), buffer);
  469.         }
  470.         goto Out;
  471.         case cnt_card32:
  472.         NEEDSPACE((sizeof *argp));
  473.         if( (ans = CirioNubGetCard32(argp)) != cnrc_ok ) goto Out;
  474.         argp++;
  475.         break;
  476.         case cnt_int32:
  477.         NEEDSPACE((sizeof *argp));
  478.         if( (ans = CirioNubGetInt32(argp)) != cnrc_ok ) goto Out;
  479.         argp++;
  480.         break;
  481.         case cnt_string: {
  482.         roundedLenWithNull = (len + 04) & (~03);
  483.         NEEDSPACE(roundedLenWithNull+(sizeof *argp));
  484.         p -= roundedLenWithNull;
  485.         if( (ans = CirioNubGetBlock8(p, roundedLen)) != cnrc_ok )
  486.             goto Out;
  487.         p[len] = 0;
  488.         *argp++ = (unsigned)(p);
  489.         }
  490.         break;
  491.         case cnt_block8:
  492.         NEEDSPACE(roundedLen+2*(sizeof *argp));
  493.         p -= roundedLen;
  494.         if( (ans = CirioNubGetBlock8(p, roundedLen)) != cnrc_ok )
  495.             goto Out;
  496.         *argp++ = len;
  497.         *argp++ = (unsigned)(p);
  498.         break;
  499.         case cnt_block16:
  500.         NEEDSPACE(roundedLen+2*(sizeof *argp));
  501.         p -= roundedLen;
  502.         if( (ans = CirioNubGetBlock16(p, roundedLen)) != cnrc_ok )
  503.             goto Out;
  504.         *argp++ = len;
  505.         *argp++ = (unsigned)(p);
  506.         break;
  507.         case cnt_block32:
  508.         NEEDSPACE(roundedLen+2*(sizeof *argp));
  509.         p -= roundedLen;
  510.         if( (ans = CirioNubGetBlock32(p, roundedLen)) != cnrc_ok )
  511.             goto Out;
  512.         *argp++ = len;
  513.         *argp++ = (unsigned)(p);
  514.         break;
  515.         default:
  516.         ans = cnrc_protocol;
  517.         goto Out;
  518.     }
  519.     }
  520. Out:
  521.     CirioDBM("-> Cirio (%d)\n", ans);
  522.     return ans;
  523. }
  524. #undef NEEDSPACE
  525.  
  526.  
  527. int
  528. CirioNubSlaveSleep(mSecs)
  529.     unsigned mSecs;
  530. {
  531.     XR_SignalState oldState;
  532.  
  533.     oldState = XR_EnableSignals();
  534.     for(;;) {
  535.         if( CirioNubWaitDescriptorReady(-1, TRUE, mSecs) != (-EINTR) ) break;
  536.     }
  537.     XR_SetSignalState(oldState);
  538. }
  539.  
  540.  
  541. static bool
  542. CirioNubWorkerProc()
  543. {
  544.     CirioNubRetCode retCode;
  545.  
  546.     int one = 1;
  547.     
  548.     if( cnd->cnd_rpcFD < 0 ) {
  549.     struct sockaddr_in hisAddr;
  550.     int hisAddrLen = (sizeof hisAddr);
  551.     int fd = CirioNubAccept(cnd->cnd_listenerFD, &hisAddr, &hisAddrLen);
  552.     if( fd < 0 ) {
  553.         (void)CirioNubSlaveSleep(2000);
  554.         return TRUE;
  555.     }
  556.     (void) setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &one, (sizeof one));
  557.     cnd->cnd_rpcFD = fd;
  558.         XR_ConsoleMsg("CirioNubWorkerProc got connection\n");
  559.     }
  560.  
  561.     while( (retCode = CirioNubProcessCall()) == cnrc_ok ) continue;
  562.  
  563.     if( retCode < cnrc_MUST_CLOSE_CONNECTION ) {
  564.     return TRUE;
  565.     } else {
  566.     (void)close(cnd->cnd_rpcFD);
  567.     cnd->cnd_rpcFD = -1;
  568.         XR_ConsoleMsg("CirioNubWorkerProc broke connection\n");
  569.     return TRUE;
  570.     }
  571. }
  572.  
  573.  
  574. static int
  575. CirioNubSlaveProc(x)
  576.     unsigned x;
  577. {
  578.     static struct sockaddr_in clearAddr;
  579.     struct sockaddr_in myAddr;
  580.     int fd = -1;
  581.     int ans, i;
  582.     CirioNubData d = (CirioNubData)(x);
  583.     short srchPort;
  584.  
  585.     /* create socket */
  586.     fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  587.     if( fd < 0 ) { ans = -1; goto Out; }
  588.  
  589.     /* bind to specified address or search for unused one */
  590.     srchPort = ((short)(d->cnd_listenerPort));
  591.     if( srchPort == 0 ) srchPort = CIRIO_NUB_LISTENER_PORT;
  592.     for( i = 0; ; i++ ) {
  593.     myAddr = clearAddr;
  594.     myAddr.sin_family = AF_INET;
  595.     myAddr.sin_port = htons(srchPort);
  596.         ans = bind( fd, &myAddr, (sizeof myAddr) );
  597.         if( ans >= 0 ) break;
  598.         if( (d->cnd_listenerPort != 0) || (i >= 20) ) { ans = -2; goto Out; }
  599.         srchPort += 1;
  600.     }
  601.     d->cnd_listenerPort = srchPort;
  602.  
  603.     ans = listen( fd, 2 );
  604.     if( ans < 0 ) { ans = -3; goto Out; }
  605.     d->cnd_listenerFD = fd; fd = -1;
  606.  
  607.     if( d->cnd_initProc != NIL ) {
  608.     (*(d->cnd_initProc))(d->cnd_initClientData);
  609.     }
  610.  
  611.     cnd = d;
  612.     XR_iope->iope_workerProc = CirioNubWorkerProc;
  613.     XR_sysArea->sa_dbData = ((XR_Pointer)(d));
  614.     XR_sysArea->sa_dbpid = XR_iope->iope_pid; /* ambush existing debugger! */
  615.     ans = d->cnd_listenerPort;
  616.  
  617. Out:
  618.     if( fd >= 0 ) (void)close(fd);
  619.     return ans;
  620. }
  621.  
  622.  
  623. /*
  624.  * Exported to CirioNubInstall.h
  625.  */
  626.  
  627. CirioNubHandle
  628. CirioNubCreateHandle(maxProcs, callBufBytes)
  629.     int maxProcs;
  630.     int callBufBytes;
  631. {
  632.     CirioNubData d;
  633.     XR_Slave slave;
  634.     int nhdrs;
  635.  
  636.     if( callBufBytes <= 0 ) callBufBytes = 2048;
  637.     if( (slave = XR_SlaveStart()) == NIL ) return(NIL);
  638.     for( nhdrs = 2; nhdrs < maxProcs; nhdrs <<= 1 ) {}
  639.     d = (CirioNubData) XR_malloc( sizeof(struct CirioNubDataRep)
  640.         + (nhdrs-1)*sizeof(struct CirioNubProcEntry *) );
  641.     d->cnd_installed = FALSE;
  642.     d->cnd_slave = slave;
  643.     d->cnd_listenerPort = 0;
  644.     d->cnd_listenerFD = -1;
  645.     d->cnd_rpcFD = -1;
  646.     d->cnd_initProc = NIL;
  647.     d->cnd_initClientData = 0;
  648.     d->cnd_callBufBytes = callBufBytes;
  649.     d->cnd_callBuf = (int *) XR_malloc( callBufBytes );
  650.     d->cnd_numHdrs = nhdrs;
  651.     bzero( (char *)(d->cnd_procEntries),
  652.             (nhdrs)*sizeof(struct CirioNubProcEntry *) );
  653.     return( (CirioNubHandle)(d) );
  654. }
  655.  
  656.  
  657. static struct XR_MLRep defaultHandleLock;
  658.  
  659. static CirioNubHandle defaultHandle = NIL;
  660.  
  661. #define MAXPROCS_MIN        8
  662. #define MAXPROCS_DEFAULT    128
  663.  
  664. #define CALLBUFBYTES_MIN    256
  665. #define CALLBUFBYTES_DEFAULT    4096
  666.  
  667. CirioNubHandle
  668. CirioNubGetDefaultHandle(maxProcs, callBufBytes)
  669.     int maxProcs;
  670.     int callBufBytes;
  671. {
  672.     CirioNubHandle h;
  673.  
  674.     if( (h = defaultHandle) == NIL ) {
  675.         if( maxProcs == 0 ) maxProcs = MAXPROCS_DEFAULT;
  676.         if( maxProcs < MAXPROCS_MIN ) maxProcs = MAXPROCS_MIN;
  677.         if( callBufBytes == 0 ) callBufBytes = CALLBUFBYTES_DEFAULT;
  678.         if( callBufBytes < CALLBUFBYTES_MIN ) callBufBytes = CALLBUFBYTES_MIN;
  679.         XR_MonitorEntry(&defaultHandleLock);
  680.         if( (h = defaultHandle) == NIL ) {
  681.             h = defaultHandle = CirioNubCreateHandle(maxProcs, callBufBytes);
  682.         }
  683.         XR_MonitorExit(&defaultHandleLock);
  684.     }
  685.     return h;
  686. }
  687.  
  688.  
  689.  
  690.  
  691. static struct XR_MLRep registrationLock;
  692.  
  693. int
  694. CirioNubRegisterProc( h, procID, proc, data )
  695.     CirioNubHandle h;
  696.     int procID;
  697.     CirioNubProc proc;
  698.     char * data;
  699. {
  700.     CirioNubData d = (CirioNubData)(h);
  701.     int hash;
  702.     struct CirioNubProcEntry *cnpe;
  703.  
  704.     hash = HASH(d,procID);
  705.     cnpe = (struct CirioNubProcEntry *)XR_malloc( sizeof (*cnpe) );
  706.     if( cnpe == NIL ) return (-1);
  707.     cnpe->cnpe_procID = procID;
  708.     cnpe->cnpe_proc = proc;
  709.     cnpe->cnpe_clientData = data;
  710.     XR_MonitorEntry(®istrationLock);
  711.     cnpe->cnpe_next = d->cnd_procEntries[hash];
  712.     d->cnd_procEntries[hash] = cnpe;
  713.     XR_MonitorExit(®istrationLock);
  714.     return 0;
  715. }
  716.  
  717. int
  718. CirioNubRegisterCProc( h, procID, proc )
  719.     CirioNubHandle h;
  720.     int procID;
  721.     CirioNubProc proc;
  722. {
  723.     return CirioNubRegisterProc( h, procID, proc, NIL );
  724. }
  725.  
  726. int
  727. CirioNubRegisterMProc( h, procID, mp )
  728.     CirioNubHandle h;
  729.     int procID;
  730.     XR_MesaProc mp;
  731. {
  732.     return CirioNubRegisterProc( h, procID,
  733.             (CirioNubProc)(mp->mp_proc), (char *)(mp) );
  734. }
  735.  
  736.  
  737. int
  738. CirioNubInstall(h, listenerPort, initProc, clientData)
  739.     CirioNubHandle h;
  740.     int listenerPort;
  741.     void (*initProc)(/* unsigned clientData */);
  742.     unsigned clientData;
  743. {
  744.     int ans;
  745.     CirioNubData d;
  746.  
  747.     d = (CirioNubData)(h);
  748.     if( d->cnd_installed ) return 0;
  749.     d->cnd_listenerPort = listenerPort;
  750.     d->cnd_initProc = initProc;
  751.     d->cnd_initClientData = clientData;
  752.     ans = XR_SlaveCall(
  753.     d->cnd_slave,
  754.     CirioNubSlaveProc,
  755.     (unsigned)(d),
  756.     XR_WAIT_FOREVER        /* actually can't take very long */
  757.     );
  758.     if( ans == 0 ) d->cnd_installed = TRUE;
  759.     return ans;
  760. }
  761.  
  762. /*
  763.  * Exported to CirioNubLocalProcs.h
  764.  */
  765.  
  766. int
  767. CirioNubLocalGetPort()
  768. {
  769.     if( cnd == NIL ) return 0;
  770.     if( cnd->cnd_listenerPort <= 0 ) return 0;
  771.     return (cnd->cnd_listenerPort);
  772. }
  773.